package tool;

import java.io.File;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.SourceDataLine;

public class Sound
{
	public static void main(String[] args)
	{
		Sound s = new Sound();
		s.play(new File("s1.wav"));
		System.out.println("o");
	}

	private boolean doLoop = false;
	private boolean doPlay = true;
	private PlayThread pthread;

	public Sound()
	{
	}

	public void setVolume(double v)
	{
		this.pthread.setVolume(v);
	}

	public void doLoop(boolean doLoop)
	{
		this.doLoop = doLoop;
	}

	public void play(File f)
	{
		try
		{
			this.pthread = new PlayThread(f);
			this.pthread.start();
			this.pthread.setVolume(2.0);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			System.exit(0);
		}
	}

	public void stop()
	{
		this.doPlay = false;
	}

	class PlayThread extends Thread
	{
		private AudioInputStream audioInputStream;
		private AudioFormat audioFormat;
		private SourceDataLine sourceDataLine;
		private double volume_wanted;
		private double volume;
		private final File f;

		public PlayThread(File f)
		{
			super();
			this.f = f;
			this.volume = -1;
		}

		public void setVolume(Double v)
		{
			this.volume_wanted = v;
		}

		private void setGainWithVolume(Double v)
		{
			// Set Volume
			FloatControl gainControl = (FloatControl) this.sourceDataLine
					.getControl(FloatControl.Type.MASTER_GAIN);
			float dB = (float) (Math.log(this.volume_wanted) / Math.log(10.0) * 20.0);
			gainControl.setValue(dB);
		}

		@Override
		public void run()
		{
			try
			{
				this.audioInputStream = AudioSystem.getAudioInputStream(this.f);
				this.audioFormat = this.audioInputStream.getFormat();
				System.out.println(this.audioFormat);

				DataLine.Info dataLineInfo = new DataLine.Info(
						SourceDataLine.class, this.audioFormat);

				this.sourceDataLine = (SourceDataLine) AudioSystem
						.getLine(dataLineInfo);

				byte tempBuffer[] = new byte[16382];

				this.sourceDataLine.open(this.audioFormat);
				this.sourceDataLine.start();
				this.setGainWithVolume(volume);
				
				int cnt;
				while ((cnt = this.audioInputStream.read(tempBuffer, 0,
						tempBuffer.length)) != -1)
				{
					if (!Sound.this.doPlay)
						break;

					if (this.volume != this.volume_wanted)
					{
						setGainWithVolume(volume_wanted);
						this.volume = this.volume_wanted;
					}

					if (cnt > 0)
						this.sourceDataLine.write(tempBuffer, 0, cnt);
				}

				this.sourceDataLine.drain();
				this.sourceDataLine.close();

				if (Sound.this.doPlay && Sound.this.doLoop)
					this.run();

			}
			catch (Exception e)
			{
				e.printStackTrace();
				System.exit(0);
			}
		}
	}
}
